<template>
    <canvas ref="canvas"></canvas>
</template>

<script setup lang="ts">
import * as THREE from 'three';
import { onMounted,onUnmounted,ref } from 'vue';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'; //轨道控制器

const canvas = ref<HTMLCanvasElement>();

let cube:any = null;
let scene:any = null;
let renderer:any = null;
let camera:any = null;
let controls:any = null;
let sceneAnimationId:any = null;
//创建场景
function testScene() {
    if(!canvas.value) return;

    canvas.value.width = window.innerWidth;
    canvas.value.height = window.innerHeight;

    //创检查场景
    scene = new THREE.Scene();

    //添加立方体到场景
    const geometry = new THREE.BoxGeometry(100,100,100);
    // const material = new THREE.MeshBasicMaterial({color:0x00ff00}); //这种材质不受光照影响
    // const material = new THREE.MeshLambertMaterial({color:0x00ff00}); 
    const material = new THREE.MeshStandardMaterial({
        color:0x00ff00,
        // transparent:true,//开启透明
        // opacity:0.5,//设置透明度
        metalness: 0.5,//金属度属性
        roughness: 0.1,//表面粗糙度
    }); 
    cube = new THREE.Mesh(geometry,material);
    cube.position.set(0,50,0); //设置位置
    scene.add(cube);

    //创建一个透视投影相机 第一个参数指的是视场角度，第二个参数指的是宽高比，第三个参数指的是近裁剪面，第四个参数指的是远裁剪面
    camera = new THREE.PerspectiveCamera(30,canvas.value?.width/canvas.value?.height,1,100000); 
    camera.position.set(400,400,400);
    // camera.lookAt(0,0,0);
    camera.lookAt(cube.position);

    //添加光照
    //平行光
    const directionalLight = new THREE.DirectionalLight(0xffffff,3); //第二个是光照强度
    // directionalLight.intensity = 3.0
    directionalLight.position.set(camera.position.x,camera.position.y,camera.position.z);
    scene.add(directionalLight);

    //创建渲染器
    renderer = new THREE.WebGLRenderer({
        canvas:canvas.value,
        antialias:true, //锯齿属性
    });
    renderer.setClearColor(0x999999); //设置背景色,所有设置都要在render之前才能生效,所以要实事动态刷新需要在动画循环中渲染
    // 获取你屏幕对应的设备像素比.devicePixelRatio告诉threejs,以免渲染模糊问题
    renderer.setPixelRatio(window.devicePixelRatio);

    //相机控件OrbitControls，支持旋转缩放移动等
    //本质上是移动摄像机的位置和朝向
    controls = new OrbitControls(camera, renderer.domElement);
    controls.enableDamping = true; // 阻尼惯性
    controls.dampingFactor = 0.05; // 阻尼惯性系数
    // controls.autoRotate = true;
    // controls.rotateSpeed = 0.5;
    // controls.enableZoom = false;
    controls.addEventListener('change', function () {
        // 浏览器控制台查看相机位置变化
        console.log('camera.position',camera.position);
        directionalLight.position.set(camera.position.x,camera.position.y,camera.position.z);
    });

    // AxesHelper：辅助观察的坐标系
    const axesHelper = new THREE.AxesHelper(150);
    scene.add(axesHelper);


    // renderer.render(scene,camera); //运行渲染循环
    renderFunc(); //渲染循环
    

    //可以不指定canvas，如下
    // const renderer = new THREE.WebGLRenderer();
    // renderer.setSize(800,800);
    // renderer.render(scene,camera); //渲染
    // document.body.appendChild(renderer.domElement);


    //监听浏览器宽高变化更新scene
    window.onresize = function () {
        // 重置渲染器输出画布canvas尺寸
        renderer.setSize(window.innerWidth, window.innerHeight);
        // 全屏情况下：设置观察范围长宽比aspect为窗口宽高比
        camera.aspect = window.innerWidth / window.innerHeight;
        // 如果相机视锥体相关参数发生了变化，需要执行updateProjectionMatrix ()方法更新相机的投影矩阵
        camera.updateProjectionMatrix();
    };
}

//动画循环
function renderFunc(){
    cube.rotateY(0.01);
    renderer.render(scene,camera); //渲染
    controls.update(); //更新控制器状态
    sceneAnimationId = requestAnimationFrame(renderFunc);
}

onMounted(()=>{
    testScene()
})

onUnmounted(()=>{
    cancelAnimationFrame(sceneAnimationId);
})


</script>

<style scoped lang="scss">
    $color-primary: #55c57a;

    canvas {
        background-color:$color-primary;
    }

</style>